"""Utility helpers for signing and code generation."""
import hmac
import hashlib
import json
import os
import secrets
from datetime import datetime, timezone
from typing import Dict
from passlib.hash import bcrypt


def get_secret_pepper() -> str:
    secret = os.getenv("SECRET_PEPPER")
    if not secret:
        raise RuntimeError("SECRET_PEPPER env var not set")
    return secret


def sign_payload(payload: Dict) -> str:
    payload_str = json.dumps(payload, sort_keys=True, separators=(",", ":"))
    return hmac.new(get_secret_pepper().encode(), payload_str.encode(), hashlib.sha256).hexdigest()


def generate_raw_code() -> str:
    alphabet = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"
    part = lambda: "".join(secrets.choice(alphabet) for _ in range(4))
    return f"PROD-{part()}-{part()}-{part()}"


def hash_code(raw: str) -> str:
    return hashlib.sha256(raw.encode()).hexdigest()


def verify_password_hash(password: str, hashed: str) -> bool:
    """Verify a plaintext password against a bcrypt hash."""
    return bcrypt.verify(password, hashed)


def get_remaining_time_str(expires_at: datetime) -> str:
    """Calculates remaining time and returns a human-readable string."""
    if not expires_at:
        return "N/A"

    # Assume naive datetime from DB is UTC and make it aware
    if expires_at.tzinfo is None:
        expires_at = expires_at.replace(tzinfo=timezone.utc)

    now = datetime.now(timezone.utc)
    if now > expires_at:
        return "已过期"

    delta = expires_at - now
    total_hours = int(delta.total_seconds() / 3600)

    if total_hours >= 24:
        days = total_hours // 24
        hours = total_hours % 24
        return f"{days}天 {hours}小时"
    
    return f"{total_hours}小时"
